package com.sgai.zero_robot.utils;

import android.content.Context;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.util.Base64;


import com.google.gson.reflect.TypeToken;

import java.lang.ref.SoftReference;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.ConcurrentMap;

/**
 * Title:
 * Description:
 * Create Date: 2023/4/12.
 * Modify User:
 * Modify Date:
 * Modify Description:
 *
 * @Author: ChenHC
 */
public class SPUtils {
	private static final String TAG = SPUtils.class.getSimpleName();
	private static SPUtils INSTANCE;
	private ConcurrentMap<String, SoftReference<Object>> mCache;
	private static String preferenceName = "sgai_app";
	private Context mContext;
	private static SharedPreferences sp;

	/**
	 * 构造方法
	 */
	public SPUtils(Context mContext){
		this.mContext = mContext;
	}

	private SPUtils(){
	}

	/**
	 * 单例（双重检查）初始化
	 */
	public static SPUtils init(Context context){
		if(INSTANCE==null){
			synchronized(SPUtils.class){
				if(INSTANCE==null){
					INSTANCE = new SPUtils(context);
					sp = context.getSharedPreferences(preferenceName, Context.MODE_PRIVATE);
				}
			}
		}
		return INSTANCE;
	}

	/**
	 * 获取单例
	 */
	public static SPUtils getInstance(){
		return INSTANCE;
	}

	/**
	 * 获取数据
	 *
	 * @param key
	 * @param defaultValue
	 * @return
	 */

	public <T> T get(String key, T defaultValue){
		if(!sp.contains(key)){
			return defaultValue;
		}
		try{
			if (defaultValue instanceof String) {
				String str = sp.getString(key, (String) defaultValue);
				return (T) str;
			} else if (defaultValue instanceof Integer) {
				Integer in = sp.getInt(key, (Integer) defaultValue);
				return (T) in;
			} else if (defaultValue instanceof Long) {
				Long lon = sp.getLong(key, (Long) defaultValue);
				return (T) lon;
			} else if (defaultValue instanceof Float) {
				Float fl = sp.getFloat(key, (Float) defaultValue);
				return (T) fl;
			} else if (defaultValue instanceof Boolean) {
				Boolean bl = sp.getBoolean(key, (Boolean) defaultValue);
				return (T) bl;
			}else{
				String objectValue = sp.getString(key, null);
				byte[] buffer = Base64.decode(objectValue, Base64.DEFAULT);
				T t = GsonUtils.fromJson(new String(buffer, StandardCharsets.UTF_8), new TypeToken<T>() {
				}.getType());
				return t;
			}
		}catch(Exception ex){
			return defaultValue;
		}
	}


	public <T> void put(String key, T t){
		try{
			SharedPreferences.Editor editor = sp.edit();
			if(t instanceof String){
				editor.putString(key, (String) t);
			}else if(t instanceof Integer){
				editor.putInt(key, (Integer) t);
			}else if(t instanceof Boolean){
				editor.putBoolean(key, (Boolean) t);
			}else if(t instanceof Float){
				editor.putFloat(key, (Float) t);
			}else if(t instanceof Long){
				editor.putLong(key, (Long) t);
			}else{
				String json = GsonUtils.toJson(t);
				String objectValue = new String(Base64.encode(json.getBytes(StandardCharsets.UTF_8), Base64.DEFAULT));
				editor.putString(key, objectValue);
			}
			SharedPreferencesCompat.apply(editor);
		}catch(Exception ex){
			ex.printStackTrace();
		}
	}

	/**
	 * remove key
	 *
	 * @param key
	 */
	public void remove(String key){
		SharedPreferences.Editor editor = sp.edit();
		editor.remove(key);
		SharedPreferencesCompat.apply(editor);
	}

	/**
	 * 判断是否包含key
	 *
	 * @param key
	 * @return
	 */
	public boolean contains(String key){
		return sp.contains(key);
	}

	/**
	 * 清空数据
	 *
	 * @param
	 */
	public void clear(){
		SharedPreferences.Editor editor = sp.edit();
		editor.clear();
		SharedPreferencesCompat.apply(editor);
	}
	//<editor-fold desc="反射调用">

	/**
	 * 创建一个解决SharedPreferencesCompat.apply方法的一个兼容类
	 *
	 * @author zhy
	 */
	private static class SharedPreferencesCompat{
		private static final Method sApplyMethod = findApplyMethod();

		/**
		 * 反射查找apply的方法
		 *
		 * @return
		 */
		@SuppressWarnings({"unchecked", "rawtypes"})
		private static Method findApplyMethod(){
			try{
				Class clz = SharedPreferences.Editor.class;
				return clz.getMethod("apply");
			}catch(NoSuchMethodException e){
			}

			return null;
		}

		/**
		 * 如果找到则使用apply执行，否则使用commit
		 *
		 * @param editor
		 */
		public static void apply(final SharedPreferences.Editor editor){
			try{
				if(sApplyMethod!=null){
					sApplyMethod.invoke(editor);
					LogUtil.d(TAG, "============apply");
					return;
				}
			}catch(IllegalArgumentException e){
			}catch(IllegalAccessException e){
			}catch(InvocationTargetException e){
			}

			new AsyncTask<Void, Void, Void>(){

				@Override
				protected Void doInBackground(Void... params){
					editor.commit();
					LogUtil.d(TAG, "============commit");
					return null;
				}
			}.execute();
		}
	}
	//</editor-fold>

}
